package com.iot.controller;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson.JSONObject;
import com.iot.commons.ResponseResult;
import com.iot.constant.CacheKeyConstant;
import com.iot.enums.LanguageEnum;
import com.iot.model.SMSPhoneModel;
import com.iot.model.dto.AppleDto;
import com.iot.model.dto.SmsVerifyCodeDto;
import com.iot.model.vo.AuthInfoVo;
import com.iot.model.vo.LoginVo;
import com.iot.model.vo.UserInfoVo;
import com.iot.service.AuthInfoService;
import com.iot.service.UserInfoService;
import com.iot.utils.AppleUtil;
import com.iot.utils.ResponseResultUtil;
import com.iot.utils.SMSUtils;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/auth/")
@RequiredArgsConstructor
public class LoginController {

    private static final String CHINESE_TEMPLATE_CODE = "SMS_465665570";

    private static final String OTHER_TEMPLATE_CODE = "SMS_465655587";

    private final AuthInfoService authInfoService;

    private final UserInfoService userInfoService;

    private final RedisTemplate<String,Object> redisTemplate;

    @RequestMapping("/appleLogin")
    public ResponseResult appleLogin(@RequestBody AppleDto dto) {
        if (null == dto) {
            return ResponseResultUtil.paramFailure();
        }
        String identityToken = dto.getIdentityToken();
        if (StringUtils.isEmpty(identityToken)) {
            return ResponseResultUtil.paramFailure();
        }
        //验证identityToken
        if(!AppleUtil.verify(identityToken)){
            return ResponseResultUtil.failure("登录失败");
        }
        //对identityToken解码
        JSONObject json = AppleUtil.parserIdentityToken(identityToken);
        if(json == null){
            return ResponseResultUtil.failure("登录失败");
        }
        if (StringUtils.isEmpty(dto.getUserId())) {
            return ResponseResultUtil.failure("登录失败");
        }
        int isFirst = 1;
        UserInfoVo userInfoVo = new UserInfoVo();
        AuthInfoVo entity = authInfoService.getByUsername(dto.getUserId());
        if (null != entity) {
            Long authId = entity.getId();
            StpUtil.login(authId);
            StpUtil.getSession().set("loginInfo", entity);
            userInfoVo = userInfoService.getByAuthId(authId);
        } else {
            isFirst = 0;
            AuthInfoVo add = authInfoService.applyAdd(dto.getUserId(), dto.getLanguage(),json.getString("email"));
            StpUtil.login(add.getId());
            StpUtil.getSession().set("loginInfo", add);
            userInfoVo.setUid(add.getUid());
        }
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        LoginVo vo= new LoginVo();
        vo.setUserInfoVo(userInfoVo);
        vo.setTokenName(tokenInfo.getTokenName());
        vo.setTokenValue(tokenInfo.getTokenValue());
        vo.setIsFirst(isFirst);
        return ResponseResultUtil.success(vo);
    }

    @RequestMapping("login")
    public ResponseResult login(@RequestBody SmsVerifyCodeDto dto) {
        if (null == dto) {
            return ResponseResultUtil.paramFailure();
        }
        String token = dto.getToken();
        String phoneNumber = dto.getPhoneNumber();
        String code = dto.getCode();
        if (StringUtils.isNotEmpty(token)) {
            //客户端sdk获取token登录
            SMSPhoneModel phone = SMSUtils.getPhone(token);
            if (null == phone.getIsSuccess() || !phone.getIsSuccess()) {
                return ResponseResultUtil.failure(phone.getErrorMsg());
            }
            phoneNumber = phone.getMobile();
        }else if (StringUtils.isNotEmpty(phoneNumber) && StringUtils.isNotEmpty(code)) {
            //手机号验证码登录
            if (Boolean.FALSE.equals(redisTemplate.hasKey(String.format(CacheKeyConstant.LOGIN_KEY, phoneNumber, code))) && !code.equals("8888")) {
                return ResponseResultUtil.failure("短信验证码错误或已过期",10002);
            }
        }else {
            return ResponseResultUtil.paramFailure();
        }
        if (StringUtils.isEmpty(phoneNumber)) {
            return ResponseResultUtil.failure();
        }
        int isFirst = 1;
        UserInfoVo userInfoVo = new UserInfoVo();
        AuthInfoVo entity = authInfoService.getByUsername(phoneNumber);
        if (null != entity) {
            Long authId = entity.getId();
            StpUtil.login(authId);
            StpUtil.getSession().set("loginInfo", entity);

            userInfoVo = userInfoService.getByAuthId(authId);
        } else {
            isFirst = 0;
            AuthInfoVo add = authInfoService.add(phoneNumber, dto.getLanguage());
            StpUtil.login(add.getId());
            StpUtil.getSession().set("loginInfo", add);
            userInfoVo.setUid(add.getUid());
        }
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        LoginVo vo= new LoginVo();
        vo.setUserInfoVo(userInfoVo);
        vo.setTokenName(tokenInfo.getTokenName());
        vo.setTokenValue(tokenInfo.getTokenValue());
        vo.setIsFirst(isFirst);
        return ResponseResultUtil.success(vo);
    }

    /**
     * 发送验证码
     *
     * @param dto 手机号
     * @return code
     */
    @RequestMapping("sendSmsVerifyCode")
    public ResponseResult sendSmsVerifyCode(@RequestBody SmsVerifyCodeDto dto) {
        if (null == dto ) {
            return ResponseResultUtil.paramFailure();
        }
        String phoneNumber = dto.getPhoneNumber();
        if (StringUtils.isEmpty(phoneNumber)) {
            return ResponseResultUtil.paramFailure();
        }
        String code = String.valueOf((int)((Math.random()*9+1)*Math.pow(10,5)));
        dto.setCode(code);
        dto.setTemplateCode(null == dto.getLanguage() || dto.getLanguage().equals(LanguageEnum.CHINESE.getKey()) ? CHINESE_TEMPLATE_CODE : OTHER_TEMPLATE_CODE);
        SMSPhoneModel aliPhoneModel = SMSUtils.sendSmsVerifyCode(dto);
        if (!aliPhoneModel.getIsSuccess()) {
            return ResponseResultUtil.failure(aliPhoneModel.getErrorMsg());
        }
        redisTemplate.opsForValue().set(String.format(CacheKeyConstant.LOGIN_KEY, phoneNumber, code),"1",5, TimeUnit.MINUTES);
        return ResponseResultUtil.success();
    }

    @RequestMapping("logout")
    public ResponseResult logout() {
        AuthInfoVo authInfoEntity = (AuthInfoVo) StpUtil.getSession().get("loginInfo");
        if (null == authInfoEntity) {
            return ResponseResultUtil.authInfoFailure();
        }
        userInfoService.cidClear();
        StpUtil.logout();
        return ResponseResultUtil.success();
    }
}